home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / blend.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  13.7 KB  |  482 lines

  1. /* $Id: blend.c,v 1.6 1997/02/15 18:27:56 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: blend.c,v $
  26.  * Revision 1.6  1997/02/15 18:27:56  brianp
  27.  * fixed a few error messages
  28.  *
  29.  * Revision 1.5  1997/01/28 22:17:19  brianp
  30.  * moved logic op blending into logic.c
  31.  *
  32.  * Revision 1.4  1997/01/04 00:13:11  brianp
  33.  * was using ! instead of ~ to invert pixel bits (ugh!)
  34.  *
  35.  * Revision 1.3  1996/09/19 00:53:31  brianp
  36.  * added missing returns after some gl_error() calls
  37.  *
  38.  * Revision 1.2  1996/09/15 14:18:10  brianp
  39.  * now use GLframebuffer and GLvisual
  40.  *
  41.  * Revision 1.1  1996/09/13 01:38:16  brianp
  42.  * Initial revision
  43.  *
  44.  */
  45.  
  46.  
  47. #ifdef DEBUG
  48. #  include <assert.h>
  49. #endif
  50. #include <stdlib.h>
  51. #include "alphabuf.h"
  52. #include "blend.h"
  53. #include "context.h"
  54. #include "dlist.h"
  55. #include "macros.h"
  56. #include "pb.h"
  57. #include "span.h"
  58. #include "types.h"
  59.  
  60.  
  61.  
  62. void gl_BlendFunc( GLcontext* ctx, GLenum sfactor, GLenum dfactor )
  63. {
  64.    if (INSIDE_BEGIN_END(ctx)) {
  65.       gl_error( ctx, GL_INVALID_OPERATION, "glBlendFunc" );
  66.       return;
  67.    }
  68.  
  69.    switch (sfactor) {
  70.       case GL_ZERO:
  71.       case GL_ONE:
  72.       case GL_DST_COLOR:
  73.       case GL_ONE_MINUS_DST_COLOR:
  74.       case GL_SRC_ALPHA:
  75.       case GL_ONE_MINUS_SRC_ALPHA:
  76.       case GL_DST_ALPHA:
  77.       case GL_ONE_MINUS_DST_ALPHA:
  78.       case GL_SRC_ALPHA_SATURATE:
  79.       case GL_CONSTANT_COLOR:
  80.       case GL_ONE_MINUS_CONSTANT_COLOR:
  81.       case GL_CONSTANT_ALPHA:
  82.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  83.          ctx->Color.BlendSrc = sfactor;
  84.          break;
  85.       default:
  86.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
  87.          return;
  88.    }
  89.  
  90.    switch (dfactor) {
  91.       case GL_ZERO:
  92.       case GL_ONE:
  93.       case GL_SRC_COLOR:
  94.       case GL_ONE_MINUS_SRC_COLOR:
  95.       case GL_SRC_ALPHA:
  96.       case GL_ONE_MINUS_SRC_ALPHA:
  97.       case GL_DST_ALPHA:
  98.       case GL_ONE_MINUS_DST_ALPHA:
  99.       case GL_CONSTANT_COLOR:
  100.       case GL_ONE_MINUS_CONSTANT_COLOR:
  101.       case GL_CONSTANT_ALPHA:
  102.       case GL_ONE_MINUS_CONSTANT_ALPHA:
  103.          ctx->Color.BlendDst = dfactor;
  104.          break;
  105.       default:
  106.          gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
  107.    }
  108.  
  109.    ctx->NewState |= NEW_RASTER_OPS;
  110. }
  111.  
  112.  
  113.  
  114. /* This is really an extension function! */
  115. void gl_BlendEquation( GLcontext* ctx, GLenum mode )
  116. {
  117.    if (INSIDE_BEGIN_END(ctx)) {
  118.       gl_error( ctx, GL_INVALID_OPERATION, "glBlendEquation" );
  119.       return;
  120.    }
  121.  
  122.    switch (mode) {
  123.       case GL_MIN_EXT:
  124.       case GL_MAX_EXT:
  125.       case GL_LOGIC_OP:
  126.       case GL_FUNC_ADD_EXT:
  127.       case GL_FUNC_SUBTRACT_EXT:
  128.       case GL_FUNC_REVERSE_SUBTRACT_EXT:
  129.          ctx->Color.BlendEquation = mode;
  130.          break;
  131.       default:
  132.          gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
  133.          return;
  134.    }
  135.  
  136.    /* This is needed to support 1.1's RGB logic ops AND
  137.     * 1.0's blending logicops.
  138.     */
  139.    if (mode==GL_LOGIC_OP && ctx->Color.BlendEnabled) {
  140.       ctx->Color.ColorLogicOpEnabled = GL_TRUE;
  141.    }
  142.    else {
  143.       ctx->Color.ColorLogicOpEnabled = GL_FALSE;
  144.    }
  145.  
  146.    ctx->NewState |= NEW_RASTER_OPS;
  147. }
  148.  
  149.  
  150.  
  151. void gl_BlendColor( GLcontext* ctx, GLclampf red, GLclampf green,
  152.             GLclampf blue, GLclampf alpha )
  153. {
  154.    ctx->Color.BlendColor[0] = CLAMP( red,   0.0, 1.0 );
  155.    ctx->Color.BlendColor[1] = CLAMP( green, 0.0, 1.0 );
  156.    ctx->Color.BlendColor[2] = CLAMP( blue,  0.0, 1.0 );
  157.    ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0, 1.0 );
  158. }
  159.  
  160.  
  161.  
  162. /*
  163.  * Do the real work of gl_blend_span() and gl_blend_pixels().
  164.  * Input:  n - number of pixels
  165.  *         mask - the usual write mask
  166.  * In/Out:  red, green, blue, alpha - the incoming and modified pixels
  167.  * Input:  rdest, gdest, bdest, adest - the pixels from the dest color buffer
  168.  */
  169. static void do_blend( GLcontext* ctx, GLuint n, const GLubyte mask[],
  170.                       GLubyte red[], GLubyte green[],
  171.                       GLubyte blue[], GLubyte alpha[],
  172.                       const GLubyte rdest[], const GLubyte gdest[],
  173.                       const GLubyte bdest[], const GLubyte adest[] )
  174. {
  175.    GLuint i;
  176.  
  177.    /* Common cases: */
  178.  
  179.    if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT
  180.        && ctx->Color.BlendSrc==GL_SRC_ALPHA
  181.        && ctx->Color.BlendDst==GL_ONE_MINUS_SRC_ALPHA) {
  182.       /* Alpha blending */
  183.       GLfloat ascale = 256.0f * ctx->Visual->InvAlphaScale;
  184.       GLint rmax = (GLint) ctx->Visual->RedScale;
  185.       GLint gmax = (GLint) ctx->Visual->GreenScale;
  186.       GLint bmax = (GLint) ctx->Visual->BlueScale;
  187.       GLint amax = (GLint) ctx->Visual->AlphaScale;
  188.       for (i=0;i<n;i++) {
  189.      if (mask[i]) {
  190.         GLint r, g, b, a;
  191.             GLint t = (GLint) ( alpha[i] * ascale );  /* t in [0,256] */
  192.             GLint s = 256 - t;
  193.         r = (red[i]   * t + rdest[i] * s) >> 8;
  194.         g = (green[i] * t + gdest[i] * s) >> 8;
  195.         b = (blue[i]  * t + bdest[i] * s) >> 8;
  196.         a = (alpha[i] * t + adest[i] * s) >> 8;
  197.         red[i]   = MIN2( r, rmax );
  198.         green[i] = MIN2( g, gmax );
  199.         blue[i]  = MIN2( b, bmax );
  200.         alpha[i] = MIN2( a, amax );
  201.      }
  202.       }
  203.    }
  204.  
  205.    /* General cases: */
  206.  
  207.    else if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT
  208.          || ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT
  209.          || ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  210.       GLfloat rmax = ctx->Visual->RedScale;
  211.       GLfloat gmax = ctx->Visual->GreenScale;
  212.       GLfloat bmax = ctx->Visual->BlueScale;
  213.       GLfloat amax = ctx->Visual->AlphaScale;
  214.       GLfloat rscale = 1.0f / rmax;
  215.       GLfloat gscale = 1.0f / gmax;
  216.       GLfloat bscale = 1.0f / bmax;
  217.       GLfloat ascale = 1.0f / amax;
  218.  
  219.       for (i=0;i<n;i++) {
  220.      if (mask[i]) {
  221.         GLint Rs, Gs, Bs, As;  /* Source colors */
  222.         GLint Rd, Gd, Bd, Ad;  /* Dest colors */
  223.         GLfloat sR, sG, sB, sA;  /* Source scaling */
  224.         GLfloat dR, dG, dB, dA;  /* Dest scaling */
  225.         GLfloat r, g, b, a;
  226.  
  227.         /* Source Color */
  228.         Rs = red[i];
  229.         Gs = green[i];
  230.         Bs = blue[i];
  231.         As = alpha[i];
  232.  
  233.         /* Frame buffer color */
  234.         Rd = rdest[i];
  235.         Gd = gdest[i];
  236.         Bd = bdest[i];
  237.         Ad = adest[i];
  238.  
  239.         /* Source scaling */
  240.         switch (ctx->Color.BlendSrc) {
  241.            case GL_ZERO:
  242.           sR = sG = sB = sA = 0.0F;
  243.           break;
  244.            case GL_ONE:
  245.           sR = sG = sB = sA = 1.0F;
  246.           break;
  247.            case GL_DST_COLOR:
  248.           sR = (GLfloat) Rd * rscale;
  249.           sG = (GLfloat) Gd * gscale;
  250.           sB = (GLfloat) Bd * bscale;
  251.           sA = (GLfloat) Ad * ascale;
  252.           break;
  253.            case GL_ONE_MINUS_DST_COLOR:
  254.           sR = 1.0F - (GLfloat) Rd * rscale;
  255.           sG = 1.0F - (GLfloat) Gd * gscale;
  256.           sB = 1.0F - (GLfloat) Bd * bscale;
  257.           sA = 1.0F - (GLfloat) Ad * ascale;
  258.           break;
  259.            case GL_SRC_ALPHA:
  260.           sR = sG = sB = sA = (GLfloat) As * ascale;
  261.           break;
  262.            case GL_ONE_MINUS_SRC_ALPHA:
  263.           sR = sG = sB = sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  264.           break;
  265.            case GL_DST_ALPHA:
  266.           sR = sG = sB = sA =(GLfloat) Ad * ascale;
  267.           break;
  268.            case GL_ONE_MINUS_DST_ALPHA:
  269.           sR = sG = sB = sA = 1.0F - (GLfloat) Ad * ascale;
  270.           break;
  271.            case GL_SRC_ALPHA_SATURATE:
  272.           if (As < 1.0F - (GLfloat) Ad * ascale) {
  273.              sR = sG = sB = (GLfloat) As * ascale;
  274.           }
  275.           else {
  276.              sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
  277.           }
  278.           sA = 1.0;
  279.           break;
  280.            case GL_CONSTANT_COLOR:
  281.           sR = ctx->Color.BlendColor[0];
  282.           sG = ctx->Color.BlendColor[1];
  283.           sB = ctx->Color.BlendColor[2];
  284.           sA = ctx->Color.BlendColor[3];
  285.           break;
  286.            case GL_ONE_MINUS_CONSTANT_COLOR:
  287.           sR = 1.0F - ctx->Color.BlendColor[0];
  288.           sG = 1.0F - ctx->Color.BlendColor[1];
  289.           sB = 1.0F - ctx->Color.BlendColor[2];
  290.           sA = 1.0F - ctx->Color.BlendColor[3];
  291.           break;
  292.            case GL_CONSTANT_ALPHA:
  293.           sR = sG = sB = sA = ctx->Color.BlendColor[3];
  294.           break;
  295.            case GL_ONE_MINUS_CONSTANT_ALPHA:
  296.           sR = sG = sB = sA = 1.0F - ctx->Color.BlendColor[3];
  297.           break;
  298.            default:
  299.                   /* this should never happen */
  300.                   abort();
  301.         }
  302.  
  303.         /* Dest scaling */
  304.         switch (ctx->Color.BlendDst) {
  305.            case GL_ZERO:
  306.           dR = dG = dB = dA = 0.0F;
  307.           break;
  308.            case GL_ONE:
  309.           dR = dG = dB = dA = 1.0F;
  310.           break;
  311.            case GL_SRC_COLOR:
  312.           dR = (GLfloat) Rs * rscale;
  313.           dG = (GLfloat) Gs * gscale;
  314.           dB = (GLfloat) Bs * bscale;
  315.           dA = (GLfloat) As * ascale;
  316.           break;
  317.            case GL_ONE_MINUS_SRC_COLOR:
  318.           dR = 1.0F - (GLfloat) Rs * rscale;
  319.           dG = 1.0F - (GLfloat) Gs * gscale;
  320.           dB = 1.0F - (GLfloat) Bs * bscale;
  321.           dA = 1.0F - (GLfloat) As * ascale;
  322.           break;
  323.            case GL_SRC_ALPHA:
  324.           dR = dG = dB = dA = (GLfloat) As * ascale;
  325.           break;
  326.            case GL_ONE_MINUS_SRC_ALPHA:
  327.           dR = dG = dB = dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
  328.           break;
  329.            case GL_DST_ALPHA:
  330.           dR = dG = dB = dA = (GLfloat) Ad * ascale;
  331.           break;
  332.            case GL_ONE_MINUS_DST_ALPHA:
  333.           dR = dG = dB = dA = 1.0F - (GLfloat) Ad * ascale;
  334.           break;
  335.            case GL_CONSTANT_COLOR:
  336.           dR = ctx->Color.BlendColor[0];
  337.           dG = ctx->Color.BlendColor[1];
  338.           dB = ctx->Color.BlendColor[2];
  339.           dA = ctx->Color.BlendColor[3];
  340.           break;
  341.            case GL_ONE_MINUS_CONSTANT_COLOR:
  342.           dR = 1.0F - ctx->Color.BlendColor[0];
  343.           dG = 1.0F - ctx->Color.BlendColor[1];
  344.           dB = 1.0F - ctx->Color.BlendColor[2];
  345.           dA = 1.0F - ctx->Color.BlendColor[3];
  346.           break;
  347.            case GL_CONSTANT_ALPHA:
  348.           dR = dG = dB = dA = ctx->Color.BlendColor[3];
  349.           break;
  350.            case GL_ONE_MINUS_CONSTANT_ALPHA:
  351.           dR = dG = dB = dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
  352.           break;
  353.            default:
  354.                   /* this should never happen */
  355.                   abort();
  356.         }
  357.  
  358. #ifdef DEBUG
  359.         assert( sR>= 0.0 && sR<=1.0 );
  360.         assert( sG>= 0.0 && sG<=1.0 );
  361.         assert( sB>= 0.0 && sB<=1.0 );
  362.         assert( sA>= 0.0 && sA<=1.0 );
  363.         assert( dR>= 0.0 && dR<=1.0 );
  364.         assert( dG>= 0.0 && dG<=1.0 );
  365.         assert( dB>= 0.0 && dB<=1.0 );
  366.         assert( dA>= 0.0 && dA<=1.0 );
  367. #endif
  368.  
  369.         /* compute blended color */
  370.         if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
  371.            r = Rs * sR + Rd * dR;
  372.            g = Gs * sG + Gd * dG;
  373.            b = Bs * sB + Bd * dB;
  374.            a = As * sA + Ad * dA;
  375.         }
  376.         else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
  377.            r = Rs * sR - Rd * dR;
  378.            g = Gs * sG - Gd * dG;
  379.            b = Bs * sB - Bd * dB;
  380.            a = As * sA - Ad * dA;
  381.         }
  382.         else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
  383.            r = Rd * dR - Rs * sR;
  384.            g = Gd * dG - Gs * sG;
  385.            b = Bd * dB - Bs * sB;
  386.            a = Ad * dA - As * sA;
  387.         }
  388.         red[i]   = (GLint) CLAMP( r, 0.0F, rmax );
  389.         green[i] = (GLint) CLAMP( g, 0.0F, gmax );
  390.         blue[i]  = (GLint) CLAMP( b, 0.0F, bmax );
  391.         alpha[i] = (GLint) CLAMP( a, 0.0F, amax );
  392.      }
  393.       }
  394.    }
  395.    else if (ctx->Color.BlendEquation==GL_MIN_EXT) {
  396.       /* EXTENSION */
  397.       for (i=0;i<n;i++) {
  398.      if (mask[i]) {
  399.         red[i]   = MIN2( red[i],   rdest[i] );
  400.         green[i] = MIN2( green[i], gdest[i] );
  401.         blue[i]  = MIN2( blue[i],  bdest[i] );
  402.         alpha[i] = MIN2( alpha[i], adest[i] );
  403.      }
  404.       }
  405.    }
  406.    else if (ctx->Color.BlendEquation==GL_MAX_EXT) {
  407.       /* EXTENSION */
  408.       for (i=0;i<n;i++) {
  409.      if (mask[i]) {
  410.         red[i]   = MAX2( red[i],   rdest[i] );
  411.         green[i] = MAX2( green[i], gdest[i] );
  412.         blue[i]  = MAX2( blue[i],  bdest[i] );
  413.         alpha[i] = MAX2( alpha[i], adest[i] );
  414.      }
  415.       }
  416.    }
  417.  
  418. }
  419.  
  420.  
  421.  
  422.  
  423.  
  424. /*
  425.  * Apply the blending operator to a span of pixels.
  426.  * Input:  n - number of pixels in span
  427.  *         x, y - location of leftmost pixel in span in window coords.
  428.  *         mask - boolean mask indicating which pixels to blend.
  429.  * In/Out:  red, green, blue, alpha - pixel values
  430.  */
  431. void gl_blend_span( GLcontext* ctx, GLuint n, GLint x, GLint y,
  432.             GLubyte red[], GLubyte green[],
  433.             GLubyte blue[], GLubyte alpha[],
  434.             GLubyte mask[] )
  435. {
  436.    GLubyte rdest[MAX_WIDTH], gdest[MAX_WIDTH];
  437.    GLubyte bdest[MAX_WIDTH], adest[MAX_WIDTH];
  438.  
  439.    /* Check if device driver can do the work */
  440.    if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
  441.       return;
  442.    }
  443.  
  444.    /* Read span of current frame buffer pixels */
  445.    gl_read_color_span( ctx, n, x, y, rdest, gdest, bdest, adest );
  446.  
  447.    do_blend( ctx, n, mask, red, green, blue, alpha, rdest, gdest, bdest, adest );
  448. }
  449.  
  450.  
  451.  
  452.  
  453.  
  454. /*
  455.  * Apply the blending operator to an array of pixels.
  456.  * Input:  n - number of pixels in span
  457.  *         x, y - array of pixel locations
  458.  *         mask - boolean mask indicating which pixels to blend.
  459.  * In/Out:  red, green, blue, alpha - array of pixel values
  460.  */
  461. void gl_blend_pixels( GLcontext* ctx,
  462.                       GLuint n, const GLint x[], const GLint y[],
  463.               GLubyte red[], GLubyte green[],
  464.               GLubyte blue[], GLubyte alpha[],
  465.               GLubyte mask[] )
  466. {
  467.    GLubyte rdest[PB_SIZE], gdest[PB_SIZE], bdest[PB_SIZE], adest[PB_SIZE];
  468.  
  469.    /* Check if device driver can do the work */
  470.    if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
  471.       return;
  472.    }
  473.  
  474.    /* Read pixels from current color buffer */
  475.    (*ctx->Driver.ReadColorPixels)( ctx, n, x, y, rdest, gdest, bdest, adest, mask );
  476.    if (ctx->RasterMask & ALPHABUF_BIT) {
  477.       gl_read_alpha_pixels( ctx, n, x, y, adest, mask );
  478.    }
  479.  
  480.    do_blend( ctx, n, mask, red, green, blue, alpha, rdest, gdest, bdest, adest );
  481. }
  482.